﻿using Microsoft.Lync.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.DirectoryServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace EmployeesAvailability
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Employee> employees;
        private DispatcherTimer timer;
        private static int REFRESH_INTERVAL = 60;
        LyncClient lyncClient;
        private ObservableCollection<Employee> _EmployeesCollection = new ObservableCollection<Employee>();

        public ObservableCollection<Employee> EmployeesCollection
        { get { return _EmployeesCollection; } }

        public MainWindow()
        {
            lyncClient = LyncClient.GetClient();
            
            GetAllEmployees();
            GetAllEmployeesAvailability();
            

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(REFRESH_INTERVAL);
            timer.Start();
            timer.Tick += new EventHandler(OnElapsedEvent);

            InitializeComponent();
        }
        

        private void OnElapsedEvent(object sender, EventArgs e)
        {
            GetAllEmployeesAvailability();

            var statusMissing = from emp in employees
                                where emp.Availability == ContactAvailability.None
                                select emp;

            var statusAvailable = from emp in employees
                                  where emp.Availability != ContactAvailability.None
                                  select emp;
        }

        private void GetAllEmployees()
        {
            employees = new List<Employee>();
            DirectorySearcher LdapSearcher = new DirectorySearcher();
            string adserver = "<Active Directory server name>";
            string searchroot = "ou=<Employee OU>,dc=<domain>,dc=com";

            LdapSearcher.SearchRoot = new DirectoryEntry(String.Format("LDAP://{0}/{1}", adserver, searchroot));
            LdapSearcher.PropertiesToLoad.Add("displayName");
            LdapSearcher.PropertiesToLoad.Add("cn");
            LdapSearcher.PropertiesToLoad.Add("department");
            LdapSearcher.PropertiesToLoad.Add("title");
            LdapSearcher.PropertiesToLoad.Add("memberOf");
            LdapSearcher.PropertiesToLoad.Add("msRTCSIP-PrimaryUserAddress");
            LdapSearcher.Filter = string.Format("(&(objectClass=user))");
            SearchResultCollection src = LdapSearcher.FindAll();

            foreach (System.DirectoryServices.SearchResult searchResult in src)
            {
                Employee employee = new Employee();

                DirectoryEntry directoryEntry = searchResult.GetDirectoryEntry();
                try
                {
                    employee.DisplayName = directoryEntry.Properties["displayName"].Value.ToString();
                    employee.Department = directoryEntry.Properties["department"].Value.ToString();
                    employee.Title = directoryEntry.Properties["title"].Value.ToString();

                    if (directoryEntry.Properties.Contains("msRTCSIP-PrimaryUserAddress"))
                    {
                        employee.SipURI = directoryEntry.Properties["msRTCSIP-PrimaryUserAddress"].Value.ToString();

                        if (employee.SipURI != null)
                        {
                            employee.LyncContact = lyncClient.ContactManager.GetContactByUri(employee.SipURI);

                            if (employee.LyncContact != null)
                                employees.Add(employee);
                        }
                    }
                    
                }
                catch (Exception ex)
                {

                    Console.WriteLine(ex.Message);
                }
            }

            var sortedList = from e in employees
                             orderby e.DisplayName
                             select e;

            _EmployeesCollection = new ObservableCollection<Employee>(sortedList);
            
        }

        private void GetAllEmployeesAvailability()
        {
            foreach (Employee employee in employees)
            {
                
                employee.Availability = GetContactAvailability(employee.LyncContact);
            }

            
            
        }

        private void PersistEmployeesAvailability()
        {
            EmployeesAvailabilityEntities model = new EmployeesAvailabilityEntities();

            foreach (Employee employee in _EmployeesCollection)
            {
                EmployeesAvailabilityHistory availabilityHistory = new EmployeesAvailabilityHistory();
                
                availabilityHistory.availability = (int)employee.Availability;
                
            }
        }

        private static string AvailabilityStateToAvailabilityVisualState(ContactAvailability availability)
        {
            switch (availability)
            {
                case ContactAvailability.Free:
                    return "Available";
                case ContactAvailability.Away:
                case ContactAvailability.TemporarilyAway:
                case ContactAvailability.FreeIdle:
                case ContactAvailability.BusyIdle:
                    return "Away";
                case ContactAvailability.Busy:
                    return "Busy";
                case ContactAvailability.DoNotDisturb:
                    return "DoNotDisturb";
                case ContactAvailability.Offline:
                    return "Offline";
                case ContactAvailability.Invalid:
                case ContactAvailability.None:
                    return "Unknown";
                default:
                    return "Unknown";
            }
        }

        //private void GetAllLyncContacts()
        //{
        //    foreach (Employee employee in employees)
        //    {
        //        employee.LyncContact = lyncClient.ContactManager.GetContactByUri(employee.SipURI);
        //    }
        //}

        private ContactAvailability GetContactAvailability(Contact lyncContact)
        {
            //int contactAvailability = 0;

            ContactAvailability availability = ContactAvailability.Invalid;
            //contactSipAddress = contactSipAddress.ToLower();

            //if (contactSipAddress.Contains("@"))
            //{
                
                availability = (ContactAvailability)lyncContact.GetContactInformation(ContactInformationType.Availability);

                
                /*switch (availability)
                {
                    case ContactAvailability.Busy:
                        {
                            contactAvailability = 2;
                            break;
                        }

                    case ContactAvailability.DoNotDisturb:
                        {
                            contactAvailability = 3;
                            break;
                        }

                    case ContactAvailability.Free:
                        {
                            contactAvailability = 1;
                            break;
                        }
                    case ContactAvailability.Away:
                        {
                            contactAvailability = 4;
                            break;
                        }
                    case ContactAvailability.FreeIdle:
                        {
                            contactAvailability = 4;
                            break;
                        }
                    case ContactAvailability.BusyIdle:
                        {
                            contactAvailability = 4;
                            break;
                        }

                    case ContactAvailability.None:
                        {
                            contactAvailability = 5;
                            break;
                        }
                    default:
                        {
                            contactAvailability = 6;
                            break;
                        }

                }*/
            //}


                return availability;
        }
    }
}
